package org.datamining.guha;

import java.util.Date;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.datamining.guha.association.FundedAssociation;
import org.datamining.guha.data.provider.DataProvider;
import org.datamining.guha.data.provider.RandomDataProvider;
import org.datamining.guha.model.LiteralSourceRow;
import org.datamining.guha.model.LiteralSourceRowImpl;
import org.datamining.guha.model.PatternTreeModel;
import org.datamining.guha.model.literal.Literal;
import org.datamining.guha.model.node.iterative.IterativeNodeFactory;
import org.datamining.guha.rule.ModelAdapter;
import org.datamining.guha.utils.VisualizerHTML;

/**
 * An example of using GUHA association mining package.
 * Now used mainly for debuging/development process.
 * This class will be removed in the future.
 *  
 * @author Lukas Vlcek
 */
public class Guha {
       
    static Log log = LogFactory.getLog(Guha.class);

    public static void main(String[] args) throws Exception {
                
        int numberOfObjects = 400;
        int bufferSize = 100;
        int rebuildEvery = 200;
        // TODO Issue if bufferSize > rebuildEvery !
        
        // A - G (including negations)
        int numberOfAtomicLiterals = 10;
        int[] classes = {2,2,1,1,1,1,2};
        
        // Used for file data
        //int numberOfAtomicLiterals = 12;
        //int[] classes = {4,6,2};
        ModelAdapter adapter = new ModelAdapter(numberOfAtomicLiterals, classes);
        
        int[] antecedentClasses = {0,1,4,6};
        int[] succedentClasses = {2,3,5};
        // Used for file data
        //int[] antecedentClasses = {0};
        //int[] succedentClasses = {1,2};
        adapter.setAntecedent(antecedentClasses);
        adapter.setSuccedent(succedentClasses);
        //log.debug("\n" + adapter);
        
        // This should go to adapter ####
        //FundedImplication fimpl = adapter.createFundedImplication(0.5, 0.96);
        FundedAssociation fimpl = adapter.createFundedAssociation(0.25, 0.5);
        //FundedImplication fimpl = adapter.createFundedImplication(0.10, 0.25);

        // ####
        log.debug("\n" + fimpl);
        
        //DataProvider dp = new DataFileReader(numberOfAtomicLiterals,
        //		"d:/work/projects/Guha/visualization/data.lst");
        //DataProvider dp = new GammaDataProvider(numberOfAtomicLiterals);
        DataProvider dp = new RandomDataProvider(numberOfAtomicLiterals);
        PatternTreeModel ptm = new PatternTreeModel(
        		numberOfAtomicLiterals, bufferSize,
        		IterativeNodeFactory.getInstance());
        
        /* ############################################### */
        // Build model
        Date start = new Date();
        
        for (int i = 0; i < numberOfObjects; i++) {

            if (/*i == 1 ||*/ (i > 0 && i%rebuildEvery == 0)) {
                log.debug(i + ": Rebuilding model");
                ptm.rebuildPatternTree();
                //log.debug(ptm);
            }
             
            List<Literal> list = dp.nextData();
            parseRow(list,ptm);
            //log.debug(ptm);
        }
        
        if (ptm.getBufferUsed() > 0) {
        	log.debug("Flushing " + ptm.getBufferUsed() + " rows from buffer.");
            ptm.flushBuffer();
        }

        Date end = new Date();
        
        //log.debug(ptm);
        
        log.debug("Data parsed: " + (end.getTime() - start.getTime()) + " ms");
        
        /* ############################################### */
        // Rebuild model
        start = new Date();
        //log.debug(ptm);
        ptm.rebuildPatternTree();
        end = new Date();
        
        //log.debug(ptm);
        
        log.debug("Rebuild model: " + (end.getTime() - start.getTime()) + " ms");
        
        /* ############################################### */
        // Evaluate rules
        start = new Date();
        List rules = fimpl.evaluate(ptm, numberOfObjects /*, adapter*/);
        end = new Date();
        
        log.debug("rules: " + rules.size());
        /* for (int i = 0; i < rules.size(); i++) { log.debug(rules.get(i)); } */
        log.debug("Rules evaluated in: " + (end.getTime() - start.getTime()) + " ms");
        
        /* ############################################### */
        // Make output into HTML
        start = new Date();
        //String visualizeDir = "d:/work/projects/Guha/visualization/";
        String visualizeDir = "output/";
        VisualizerHTML.generateHTML(visualizeDir);
        VisualizerHTML.generateModel(visualizeDir, ptm, numberOfObjects, adapter);
        VisualizerHTML.generateRules(visualizeDir, fimpl, rules);
        //VisualizerHTML.generateXml(visualizeDir, ptm.getRoot());
        end = new Date();
        log.debug("Reports created: " + (end.getTime() - start.getTime()) + " ms");
    }
    
    private static void parseRow(List<Literal> list, PatternTreeModel ptm) {
        
        LiteralSourceRow row = new LiteralSourceRowImpl(list);
        //log.info("Adding new row: " + row);
        ptm.parseSourceRow(row);
    }
}
